﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using UnityEditor;
using UnityEngine;

public class USControl : Editor
{
    private static float additionalFloatingWidth = 0f;
    private static float currentScrubPosition = 0f;
    private static bool draggingTimeline = false;
    private static bool extendingFloatingWidth = false;
    private static float floatingPaneWidth = 150f;
    private static Texture markerTexture = null;
    private static bool mouseDrag = false;
    private static bool mouseDragScrub = false;
    private static float mousePosOnTimeline = 0f;
    private static float playbackPaneHeight = 15f;
    private static float scrollbarWidth = 15f;
    private static USScrollInfo scrollInfo = null;
    private static Texture scrubHeadTexture = null;
    private static Texture scrubTailTexture = null;
    private static USSequencer sequence = null;
    private static float totalPixelHeightOfTimeline = 1f;
    private static float totalPixelWidthOfTimeline = 1f;
    private static List<UndoRedoFunction> undoRedoList = new List<UndoRedoFunction>();
    public static USZoomInfo zoomInfo = null;

    public static float convertEventPanePositionToTime(float pos)
    {
        return ((pos / zoomInfo.currentXMarkerDist) * zoomInfo.meaningOfEveryMarker);
    }

    public static float convertTimeToEventPanePosition(float time)
    {
        return ((time / zoomInfo.meaningOfEveryMarker) * zoomInfo.currentXMarkerDist);
    }

    public static void OnGUI(Rect position, Rect passedArea, USSequencer sequencer)
    {
        if (((zoomInfo != null) && (sequencer != null)) && (sequence != sequencer))
        {
            zoomInfo.currentZoom = 1f;
        }
        sequence = sequencer;
        UpdateDisplayData(sequencer);
        RetainOrUpdateZoomInfo();
        RetainOrUpdateScrollInfo();
        if (mouseDragScrub && (Event.current.type == EventType.MouseUp))
        {
            mouseDragScrub = false;
            mouseDrag = false;
        }
        Rect screenRect = passedArea;
        GUILayout.BeginArea(screenRect, string.Empty, "box");
        UpdateGrabHandle();
        Rect rect2 = new Rect(floatingPaneWidth, 0f, (screenRect.width - floatingPaneWidth) - scrollbarWidth, playbackPaneHeight);
        GUILayout.BeginArea(rect2, string.Empty, "box");
        UpdateTimeMarkerArea(rect2, sequencer);
        GUILayout.EndArea();
        Rect rect3 = new Rect(0f, playbackPaneHeight, screenRect.width - scrollbarWidth, (screenRect.height - playbackPaneHeight) - scrollbarWidth);
        GUILayout.BeginArea(rect3, string.Empty, "box");
        UpdateTimelineArea(rect3, sequencer);
        Rect rect4 = rect3;
        rect4.y = 0f;
        rect4.y -= scrollInfo.currentScroll.y;
        rect4.height = USControlTimelines.GetDisplayHeight(sequencer);
        GUILayout.BeginArea(rect4);
        USControlTimelines.Display(rect3.width, rect4.height, floatingPaneWidth, scrollInfo.currentScroll.x, sequencer);
        GUILayout.EndArea();
        totalPixelHeightOfTimeline = USControlTimelines.GetDisplayHeight(sequencer);
        scrollInfo.visibleScroll.y = rect3.height - 45f;
        if (scrollInfo.visibleScroll.y > totalPixelHeightOfTimeline)
        {
            scrollInfo.visibleScroll.y = totalPixelHeightOfTimeline;
        }
        Rect thisArea = new Rect(floatingPaneWidth, 0f, rect3.width - floatingPaneWidth, rect3.height);
        RenderScrubLine(thisArea, sequencer);
        GUILayout.EndArea();
        Rect rect6 = new Rect(rect3.width, 0f, scrollbarWidth, rect3.height + scrollbarWidth);
        scrollInfo.currentScroll.y = GUI.VerticalScrollbar(rect6, scrollInfo.currentScroll.y, scrollInfo.visibleScroll.y, 0f, totalPixelHeightOfTimeline);
        Rect rect7 = new Rect(0f, rect3.height + scrollbarWidth, rect3.width, scrollbarWidth);
        scrollInfo.currentScroll.x = GUI.HorizontalScrollbar(rect7, scrollInfo.currentScroll.x, scrollInfo.visibleScroll.x, 0f, totalPixelWidthOfTimeline);
        GUILayout.EndArea();
        Event current = Event.current;
        if ((((current.type == EventType.MouseDown) || (current.type == EventType.MouseUp)) || (current.type == EventType.MouseDrag)) && !current.alt)
        {
            Vector2 mousePosition = current.mousePosition;
            mousePosition.x -= screenRect.x;
            mousePosition.x -= floatingPaneWidth;
            mousePosition.y -= screenRect.y;
            mousePosition.y -= playbackPaneHeight;
            mousePosition.y += scrollInfo.currentScroll.y;
            mousePosition.x += scrollInfo.currentScroll.x;
            USControlTimelines.HandleEvent(sequencer, current.type, current.button, mousePosition);
        }
        if ((Event.current.type == EventType.KeyDown) && (Event.current.keyCode == KeyCode.Delete))
        {
            USControlTimelines.ProcessDelete(sequence);
        }
        if (USControlTimelines.IsBoxSelecting && USControlTimelines.HasStartedDrag)
        {
            Vector2 vector2 = current.mousePosition;
            Vector2 dragStartPosition = USControlTimelines.DragStartPosition;
            dragStartPosition.x += screenRect.x + floatingPaneWidth;
            dragStartPosition.y += screenRect.y + playbackPaneHeight;
            dragStartPosition.y -= scrollInfo.currentScroll.y;
            dragStartPosition.x -= scrollInfo.currentScroll.x;
            Vector2 vector4 = dragStartPosition;
            Vector2 vector5 = vector2;
            if (vector2.x < dragStartPosition.x)
            {
                vector4.x = vector2.x;
                vector5.x = dragStartPosition.x;
            }
            if (vector2.y < dragStartPosition.y)
            {
                vector4.y = vector2.y;
                vector5.y = dragStartPosition.y;
            }
            Vector2 vector6 = vector5 - vector4;
            Rect rect8 = new Rect(vector4.x, vector4.y, vector6.x, vector6.y);
            if (!EditorGUIUtility.isProSkin)
            {
                GUI.Box(rect8, string.Empty, USEditorUtility.USeqSkin.box);
            }
            else
            {
                GUI.Box(rect8, string.Empty);
            }
            rect8.y += scrollInfo.currentScroll.y;
            rect8.x += scrollInfo.currentScroll.x;
            rect8.x -= screenRect.x + floatingPaneWidth;
            rect8.y -= screenRect.y + playbackPaneHeight;
            USControlTimelines.SelectionArea = rect8;
        }
    }

    public static void OnLoad()
    {
        typeof(EditorApplication).GetField("undoRedoPerformed", BindingFlags.NonPublic | BindingFlags.Static).SetValue(null, new EditorApplication.CallbackFunction(USControl.OnUndoRedo));
    }

    private static void OnUndoRedo()
    {
        foreach (UndoRedoFunction function in undoRedoList)
        {
            function();
        }
    }

    public static void RecursivelyAddDisplayData(Transform parent)
    {
        IEnumerator enumerator = parent.GetEnumerator();
        try
        {
        Label_01C3:
            while (enumerator.MoveNext())
            {
                Transform current = (Transform) enumerator.Current;
                string key = "Sequencer-" + current.name + "-expanded";
                if (!EditorTimelineData.Data.ContainsKey(current))
                {
                    if (USSequencerUtility.IsEvent(current))
                    {
                        goto Label_01C3;
                    }
                    EditorTimelineData data = new EditorTimelineData();
                    data.expanded = false;
                    if (EditorPrefs.HasKey(key))
                    {
                        data.expanded = EditorPrefs.GetBool(key);
                    }
                    EditorTimelineData.Data.Add(current, data);
                }
                else
                {
                    if ((current.childCount > 0) && USSequencerUtility.IsTimelineContainer(current))
                    {
                        EditorTimelineData.Data[current].expandable = true;
                    }
                    else
                    {
                        EditorTimelineData.Data[current].expandable = false;
                    }
                    EditorPrefs.SetBool(key, EditorTimelineData.Data[current].expanded);
                    EditorTimelineData.Data[current].hasAnimatedChildren = false;
                    if (USSequencerUtility.IsTimelineContainer(current) && (current.childCount > 0))
                    {
                        foreach (USTimelineBase base2 in current.GetComponent<USTimelineContainer>().Timelines)
                        {
                            USTimelineEvent event2 = base2 as USTimelineEvent;
                            if ((event2 != null) && (event2.EventCount > 0))
                            {
                                EditorTimelineData.Data[current].hasAnimatedChildren = true;
                            }
                            USTimelineProperty property = base2 as USTimelineProperty;
                            if ((property != null) && (property.Properties.Count > 0))
                            {
                                EditorTimelineData.Data[current].hasAnimatedChildren = true;
                            }
                            if (USSequencerUtility.IsObserverTimeline(base2.transform))
                            {
                                EditorTimelineData.Data[current].hasAnimatedChildren = true;
                            }
                        }
                    }
                }
                RecursivelyAddDisplayData(current);
            }
        }
        finally
        {
            IDisposable disposable = enumerator as IDisposable;
            if (disposable != null)
            {
            	disposable.Dispose();
            }
        }
    }

    public static void RegisterUndoRedo(UndoRedoFunction function)
    {
        undoRedoList.Add(function);
    }

    private static void RenderScrubLine(Rect thisArea, USSequencer sequencer)
    {
        string path = "TimelineScrubTail";
        if (scrubTailTexture == null)
        {
            scrubTailTexture = Resources.Load(path, typeof(Texture)) as Texture;
        }
        if (scrubTailTexture == null)
        {
            Debug.Log("没有找到贴图TimelineScrubTail, 请检查资源文件夹是否存在");
        }
        Rect position = new Rect(thisArea.x + currentScrubPosition, 0f, 1f, thisArea.height);
        if (position.x >= thisArea.x)
        {
            Color color = GUI.color;
            GUI.color = new Color(1f, 0.1f, 0.1f, 0.65f);
            GUI.DrawTexture(position, scrubTailTexture);
            GUI.color = color;
        }
    }

    private static void RetainOrUpdateScrollInfo()
    {
        string key = "uSequencer-Prefs-CurrentScroll-X";
        string str2 = "uSequencer-Prefs-CurrentScroll-Y";
        string str3 = "uSequencer-Prefs-VisibleScroll-X";
        string str4 = "uSequencer-Prefs-VisibleScroll-Y";
        if (scrollInfo == null)
        {
            scrollInfo = new USScrollInfo();
            if (EditorPrefs.HasKey(key))
            {
                scrollInfo.currentScroll.x = EditorPrefs.GetFloat(key);
            }
            if (EditorPrefs.HasKey(str2))
            {
                scrollInfo.currentScroll.y = EditorPrefs.GetFloat(str2);
            }
            if (EditorPrefs.HasKey(str3))
            {
                scrollInfo.visibleScroll.x = EditorPrefs.GetFloat(str3);
            }
            if (EditorPrefs.HasKey(str4))
            {
                scrollInfo.visibleScroll.y = EditorPrefs.GetFloat(str4);
            }
        }
        EditorPrefs.SetFloat(key, scrollInfo.currentScroll.x);
        EditorPrefs.SetFloat(str2, scrollInfo.currentScroll.y);
        EditorPrefs.SetFloat(str3, scrollInfo.visibleScroll.x);
        EditorPrefs.SetFloat(str4, scrollInfo.visibleScroll.y);
    }

    private static void RetainOrUpdateZoomInfo()
    {
        string key = "uSequencer-Prefs-CurrentZoom";
        if (zoomInfo == null)
        {
            zoomInfo = new USZoomInfo();
            if (EditorPrefs.HasKey(key))
            {
                zoomInfo.currentZoom = EditorPrefs.GetFloat(key);
            }
        }
        EditorPrefs.SetFloat(key, zoomInfo.currentZoom);
    }

    public static void SaveObjectValueInAnimationMode(Transform parent, ref List<UnityEngine.Object> listObjs)
    {
        if ((parent != null) && (parent.gameObject != null))
        {
            listObjs.Add(parent);
            listObjs.Add(parent.gameObject);
            Component[] components = parent.gameObject.GetComponents<Component>();
            for (int i = 0; i < components.Length; i++)
            {
                listObjs.Add(components[i]);
            }
            IEnumerator enumerator = parent.GetEnumerator();
            try
            {
                while (enumerator.MoveNext())
                {
                    Transform current = (Transform) enumerator.Current;
                    SaveObjectValueInAnimationMode(current, ref listObjs);
                }
            }
            finally
            {
                IDisposable disposable = enumerator as IDisposable;
                if (disposable != null)
                {
                	disposable.Dispose();
                }
            }
        }
    }

    public static void SetTime(float time, USSequencer sequence)
    {
        StartProcessingAnimationMode(sequence);
        Undo.RegisterUndo(sequence, "设置头部");
        sequence.RunningTime = time;
    }

    public static void StartProcessingAnimationMode(USSequencer sequencer)
    {
        if (!AnimationUtility.InAnimationMode() && !Application.isPlaying)
        {
            List<UnityEngine.Object> listObjs = new List<UnityEngine.Object>();
            foreach (Transform transform in sequencer.ObservedObjects)
            {
                SaveObjectValueInAnimationMode(transform, ref listObjs);
            }
            AnimationUtility.StartAnimationMode(listObjs.ToArray());
        }
    }

    public static void StopProcessingAnimationMode()
    {
        if (AnimationUtility.InAnimationMode() && !Application.isPlaying)
        {
            if (sequence != null)
            {
                sequence.RunningTime = 0f;
            }
            AnimationUtility.StopAnimationMode();
        }
    }

    public static void UpdateDisplayData(USSequencer sequencer)
    {
        RecursivelyAddDisplayData(sequencer.transform);
    }

    private static void UpdateFloatingArea(Rect thisArea, USSequencer sequencer)
    {
        Rect rect = new Rect(0f, -scrollInfo.currentScroll.y, thisArea.width, 16f);
        Rect rect2 = rect;
        rect2.height = rect.y + rect.height;
        totalPixelHeightOfTimeline = (rect.y + scrollInfo.currentScroll.y) - rect.height;
        scrollInfo.visibleScroll.y = thisArea.height - 45f;
        if (scrollInfo.visibleScroll.y > totalPixelHeightOfTimeline)
        {
            scrollInfo.visibleScroll.y = totalPixelHeightOfTimeline;
        }
    }

    private static void UpdateGrabHandle()
    {
        Event current = Event.current;
        floatingPaneWidth = 150f;
        Rect screenRect = new Rect((floatingPaneWidth + additionalFloatingWidth) - 10f, 0f, 10f, playbackPaneHeight);
        GUILayout.BeginArea(screenRect, string.Empty, "box");
        if ((current.type == EventType.MouseDown) && (current.button == 0))
        {
            Rect rect2 = screenRect;
            rect2.x = 0f;
            if (rect2.Contains(current.mousePosition))
            {
                extendingFloatingWidth = true;
            }
        }
        if (extendingFloatingWidth && (current.type == EventType.MouseDrag))
        {
            additionalFloatingWidth += Event.current.delta.x;
        }
        floatingPaneWidth += additionalFloatingWidth;
        GUILayout.EndArea();
        if (current.type == EventType.MouseUp)
        {
            extendingFloatingWidth = false;
        }
    }

    private static void UpdateTimelineArea(Rect thisArea, USSequencer sequencer)
    {
        Event current = Event.current;
        if (thisArea.Contains(current.mousePosition))
        {
            if (current.type == EventType.ScrollWheel)
            {
                scrollInfo.currentScroll += (Vector2) (current.delta * USPreferenceWindow.ScrollFactor);
                current.Use();
            }
            if (current.alt)
            {
                draggingTimeline = true;
            }
            else
            {
                draggingTimeline = false;
            }
            if (draggingTimeline && (Event.current.type == EventType.MouseDrag))
            {
                scrollInfo.currentScroll.x -= Event.current.delta.x;
                scrollInfo.currentScroll.y -= Event.current.delta.y;
                Event.current.Use();
            }
        }
    }

    private static void UpdateTimeMarkerArea(Rect thisArea, USSequencer sequencer)
    {
        string path = "TimelineMarker";
        if (markerTexture == null)
        {
            markerTexture = Resources.Load(path, typeof(Texture)) as Texture;
        }
        if (markerTexture == null)
        {
            Debug.Log("没有找到贴图TimelineMarker, 请检查资源文件夹是否存在");
        }
        string str2 = "TimelineScrubHead";
        if (scrubHeadTexture == null)
        {
            scrubHeadTexture = Resources.Load(str2, typeof(Texture)) as Texture;
        }
        if (scrubHeadTexture == null)
        {
            Debug.Log("没有找到贴图TimelineScrubHead, 请检查资源文件夹是否存在");
        }
        Event current = Event.current;
        Rect rect = thisArea;
        rect.x = 0f;
        rect.y = 0f;
        float num = Mathf.Ceil(zoomInfo.currentZoom);
        float num2 = Mathf.Floor(zoomInfo.currentZoom);
        float num3 = (zoomInfo.currentZoom - num2) / (num / num);
        float num4 = 60f;
        float num5 = num4 * 2f;
        zoomInfo.currentXMarkerDist = (num5 * num3) + (num4 * (1f - num3));
        float num6 = thisArea.height * 0.1f;
        float height = thisArea.height * 0.8f;
        float num8 = (height * num3) + (num6 * (1f - num3));
        float num9 = thisArea.width / num4;
        zoomInfo.meaningOfEveryMarker = Mathf.Ceil(sequencer.Duration / num9);
        for (int i = Mathf.FloorToInt(zoomInfo.currentZoom); i > 1; i--)
        {
            zoomInfo.meaningOfEveryMarker *= 0.5f;
        }
        totalPixelWidthOfTimeline = zoomInfo.currentXMarkerDist * (sequencer.Duration / zoomInfo.meaningOfEveryMarker);
        scrollInfo.visibleScroll.x = (thisArea.width / zoomInfo.currentXMarkerDist) * zoomInfo.currentXMarkerDist;
        if (scrollInfo.visibleScroll.x > totalPixelWidthOfTimeline)
        {
            scrollInfo.visibleScroll.x = totalPixelWidthOfTimeline;
        }
        float num11 = 0f;
        Rect position = new Rect(-scrollInfo.currentScroll.x, 0f, 1f, height);
        while (position.x < thisArea.width)
        {
            if (num11 > sequencer.Duration)
            {
                break;
            }
            GUI.DrawTexture(position, markerTexture);
            GUI.Label(new Rect(position.x + 2f, position.y, 40f, thisArea.height), num11.ToString());
            for (int j = 1; j <= 10; j++)
            {
                float num13 = position.x + ((zoomInfo.currentXMarkerDist / 10f) * j);
                Rect rect3 = position;
                rect3.x = num13;
                rect3.height = num6;
                if (j == 5)
                {
                    rect3.height = num8;
                }
                GUI.DrawTexture(rect3, markerTexture);
            }
            position.x += zoomInfo.currentXMarkerDist;
            num11 += zoomInfo.meaningOfEveryMarker;
        }
        currentScrubPosition = convertTimeToEventPanePosition(sequencer.RunningTime) - scrollInfo.currentScroll.x;
        float num14 = 5f;
        Rect rect4 = new Rect(currentScrubPosition - num14, 0f, num14 * 2f, rect.height);
        Color color = GUI.color;
        GUI.color = new Color(1f, 0.1f, 0.1f, 0.65f);
        GUI.DrawTexture(rect4, scrubHeadTexture);
        GUI.color = color;
        rect4.x += rect4.width;
        rect4.width = 100f;
        GUI.Label(rect4, sequencer.RunningTime.ToString());
        mousePosOnTimeline = convertEventPanePositionToTime(current.mousePosition.x + scrollInfo.currentScroll.x);
        if (mouseDragScrub && (current.type == EventType.MouseDrag))
        {
            sequencer.RunningTime = mousePosOnTimeline;
            if (!sequencer.IsPlaying)
            {
                foreach (USTimelineContainer container in sequencer.TimelineContainers)
                {
                    container.ProcessTimelines(sequencer.RunningTime);
                }
            }
            current.Use();
        }
        if (rect.Contains(current.mousePosition))
        {
            if (!mouseDrag && (current.type == EventType.MouseDown))
            {
                Undo.SetSnapshotTarget(sequencer, "设置头部");
                Undo.CreateSnapshot();
                Undo.RegisterSnapshot();
                StartProcessingAnimationMode(sequencer);
                mouseDrag = true;
                mouseDragScrub = true;
                sequencer.RunningTime = mousePosOnTimeline;
                if (!sequencer.IsPlaying)
                {
                    foreach (USTimelineContainer container2 in sequencer.TimelineContainers)
                    {
                        container2.ProcessTimelines(sequencer.RunningTime);
                    }
                }
                current.Use();
            }
            if (current.type == EventType.ScrollWheel)
            {
                float num17 = current.delta.y * USPreferenceWindow.ZoomFactor;
                if (Event.current.control)
                {
                    num17 *= 10f;
                }
                zoomInfo.currentZoom += num17;
                if (zoomInfo.currentZoom <= 1f)
                {
                    zoomInfo.currentZoom = 1f;
                }
                scrollInfo.currentScroll.x += current.delta.x;
                current.Use();
            }
        }
    }

    public static bool ShowOnlyAnimated
    {
        get
        {
            string key = "Sequencer-ShowOnlyAnimated";
            return (EditorPrefs.HasKey(key) && EditorPrefs.GetBool(key));
        }
        set
        {
            string key = "Sequencer-ShowOnlyAnimated";
            EditorPrefs.SetBool(key, value);
        }
    }

    public delegate void UndoRedoFunction();
}

